package utils;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Root;

import utils.UserDAORemote;
import model.Domain;
import model.Domain_;
import model.User;
import model.User_;
import model.Usertype;
import model.Usertype_;
import dtos.UserDTO;

/**
 * Session Bean implementation class UserDAO
 * 
 * @author Radulescu Cristina
 * @author Pop Loredana
 */

@Stateless
public class UserDAO implements UserDAORemote {

	/**
	 * Default constructor.
	 */

	@PersistenceContext
	EntityManager em;

	@EJB
	Conv conv;

	public UserDAO() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * Inserts user in database.
	 */

	@Override
	public void insertUser(UserDTO ud) {
		User r = em.find(User.class, ud.getId());
		User r1 = conv.fromEntityUserDTO(ud);
		if (r == null) {
			em.persist(r1);
		} else {
			em.merge(r1);
		}
	}

	/**
	 * Method that searches for a User given the user ID
	 * 
	 * @param id
	 *            an integer value
	 * @return a user with the corresponding id
	 */
	@Override
	public UserDTO getUser(int id) {
		if (em.find(User.class, id) == null)
			return null;
		return conv.fromEntityUser(em.find(User.class, id));
	}

	@Override
	public void updateUser(UserDTO ud) {
		if (em.find(User.class, ud.getId()) != null)
			em.merge(conv.fromEntityUserDTO(ud));
	}

	/**
	 * Returns a list of UserDTOs with matching username
	 * 
	 * @param username
	 *            the username of the user we are searching for
	 * @return a list o users
	 */
	@Override
	public List<UserDTO> getAllUsersByUsername(String username) {
		List<UserDTO> resultUserList = new ArrayList<>();
		List<User> users = getAllUsers();
		for (User u : users) {
			if (u.getUsername().equals(username)) {
				resultUserList.add(conv.fromEntityUser(u));
			}
		}
		return resultUserList;
	}

	/**
	 * Method used to update the password of a certain user
	 * 
	 * @param user
	 *            a UserDTO object used for identifying the user whom password
	 *            we have to change
	 * @param password
	 *            the new password of the account
	 */
	@Override
	public String updateUserPassword(UserDTO user, String password) {
		String md5Pass = new Codification().md5(user.getPassword());
		String error=checkPassword(getAllUsers(), user.getUsername(),md5Pass);
		System.out.println("eroarea este "+error);
		if(error.equals("")){
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaUpdate<User> update = cb.createCriteriaUpdate(User.class);
		Root<User> e = update.from(User.class);
		update.set("password", new Codification().md5(password));
		update.where(cb.and(
				cb.equal(e.get("username"), user.getUsername()),
				cb.equal(e.get("password"), md5Pass)));
		
		Query query = em.createQuery(update);
		query.executeUpdate();
		}
		
		return error;
	}
	
	/**
	 * Method who makes aproximattly the same thing as above but doesn't verify user password
	 * 
	 */
	@Override
	public void updateUserPasswordWithCodification(UserDTO user, String password) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaUpdate<User> update = cb.createCriteriaUpdate(User.class);
		Root<User> e = update.from(User.class);
		System.out.println("user-ul activ unde ar trebui inserat este "+user.getUsername());
		update.set("password", new Codification().md5(password));
		update.where(cb.equal(e.get("username"), user.getUsername()));
		
		Query query = em.createQuery(update);
		query.executeUpdate();
		}
		
		
	

	/**
	 * Method used to modify different data(email/name) of a certain user
	 * 
	 * @param user
	 *            a UserDTO object used for identifying the user whom data we
	 *            have to change and the changed data
	 * @param verifPass
	 *            a string containing a password given by the user
	 * @return a string with the errors, if any
	 */
	@Override
	public String updateUserProfile(UserDTO user) {
		// public String updateUser(UserDTO user, String verifPass) {
		String error = "";

		List<User> users = getAllUsers();

		error = error + checkEmailDuplicate(users, user);
		// error = error + checkPassword(users, user);

		if (error.equals("")) {
			CriteriaBuilder cb = em.getCriteriaBuilder();

			CriteriaUpdate<User> update = cb.createCriteriaUpdate(User.class);
			Root<User> e = update.from(User.class);

			update.set("name", user.getName());
			update.set("email", user.getEmail());
			// update.where(cb.and(cb.equal(e.get("username"),
			// user.getUsername()),
			// cb.equal(e.get("password"), verifPass)));
			update.where(cb.and(cb.equal(e.get("username"), user.getUsername())));

			Query query = em.createQuery(update);
			query.executeUpdate();
		}
		return error;
	}

	/**
	 * Method for getting the user list
	 * 
	 * @return list of users
	 */
	private List<User> getAllUsers() {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		TypedQuery<User> q = em.createQuery(cq);

		return q.getResultList();
	}

	/**
	 * Method for checking if the entered password is the same as the one from
	 * the database
	 * 
	 * @param users
	 *            list of all the users
	 * @param user
	 *            a UserDTO object containing a User from the list with modified
	 *            password
	 * @return error string
	 */
	private String checkPassword(List<User> users, String username, String pass) {
		for (User u : users) {
			if (u.getUsername().equals(username)) {
				if (!u.getPassword().equals(pass)) {

					return "Wrong password";
				}
			}
		}
		return "";

	}

	/**
	 * Checking the database for email addresses duplicates
	 * 
	 * @param users
	 *            list of all the users
	 * @param user
	 *            a UserDTO object containing a User from the list with modified
	 *            email
	 * @return error string
	 */
	private String checkEmailDuplicate(List<User> users, UserDTO user) {
		int count = 0;
		for (User u : users) {
			if (u.getEmail().equals(user.getEmail())) {
				if (u.getId() != user.getId()) {
					count++;
				}

			}
		}

		if (count > 0) {
			return "Email duplicate detected";
		}
		return "";
	}

	/**
	 * Method for getting the user list
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getAllUsersDTO() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		TypedQuery<User> q = em.createQuery(cq);

		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to delete user
	 * 
	 * @param ud
	 *            of type user
	 */
	@Override
	public void deleteUser(UserDTO ud) {
		User r = em.find(User.class, ud.getId());
		em.remove(r);
	}

	/**
	 * Method used to update username
	 * 
	 * @param user
	 *            of type username
	 * @param username
	 *            of type String
	 */
	@Override
	public void updateUsername(UserDTO user, String username) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaUpdate<User> update = cb.createCriteriaUpdate(User.class);
		Root<User> e = update.from(User.class);
		update.set("username", username);
		update.where(cb.equal(e.get("username"), user.getUsername()));
		Query query = em.createQuery(update);
		query.executeUpdate();
	}

	/**
	 * Method used to get all users by usertype
	 * 
	 * @param idUsertype
	 * @return list of usersDto
	 */

	@Override
	public List<UserDTO> getUsersByUsertype(int idUsertype) {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		TypedQuery<User> q = em.createQuery(cq);

		List<User> users = q.getResultList();

		for (User u : users) {
			Usertype usertype = u.getUsertype();
			if (usertype.getId() == idUsertype) {
				resultlist.add(conv.fromEntityUser(u));
			}
		}
		return resultlist;
	}

	/**
	 * Method used to get Admin
	 * 
	 * @return userDto
	 */
	@Override
	public UserDTO getAdmin() {
		int idAdminUsertype = 1;
		List<UserDTO> users = getUsersByUsertype(idAdminUsertype);
		if (!users.isEmpty()) {
			return users.get(0);
		}
		return null;
	}

	/**
	 * Method used to get all Inactive Office Managers
	 * 
	 * @return list of usersDto
	 */
	@Override
	public List<UserDTO> getInactiveOfficeManagers() {
		List<UserDTO> resultlist = new ArrayList<>();
		UserDTO admin = getAdmin();

		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		TypedQuery<User> q = em.createQuery(cq);

		List<User> users = q.getResultList();

		for (User u : users) {
			User replacementUser = u.getUser();
			if (u.getIsactive() == 0 && replacementUser != null
					&& replacementUser.getId() == admin.getId()) {
				resultlist.add(conv.fromEntityUser(u));
			}
		}
		return resultlist;
	}

	/**
	 * @author Katona Gabor
	 * @param String
	 *            email
	 * @return UserDTO Returns the user with the specific email address if
	 *         exists, else returns null
	 */
	@Override
	public UserDTO getUserDTOByEmail(String email) {
		UserDTO tempUser = null;
		List<User> users = getAllUsers();
		for (User u : users) {
			if (u.getEmail().equals(email)) {
				tempUser = conv.fromEntityUser(u);
			}
		}
		return tempUser;
	}

	/**
	 * Method used to check if user is office manager
	 * 
	 * @return boolean
	 * @param userDto
	 */
	@Override
	public boolean isOfficeManager(UserDTO ud) {
		User u = em.find(User.class, ud.getId());
		if (u == null) {
			return false;
		} else {
			Usertype usertype = u.getUsertype();
			if (usertype.getId() == 2) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Method used to check if user is Technichan
	 * 
	 * @return boolean
	 * @param user
	 */
	@Override
	public boolean isTechnician(UserDTO ud) {
		User u = em.find(User.class, ud.getId());
		if (u == null) {
			return false;
		} else {
			Usertype usertype = u.getUsertype();
			if (usertype.getId() == 3) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Method used to check if user is Admin
	 * 
	 * @return boolean
	 * @param userDto
	 */
	@Override
	public boolean isAdmin(UserDTO ud) {
		User u = em.find(User.class, ud.getId());
		if (u == null) {
			return false;
		} else {
			Usertype usertype = u.getUsertype();
			if (usertype.getId() == 1) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Method used to check if user is Basic User
	 * 
	 * @return boolean
	 * @param userDto
	 */
	@Override
	public boolean isBasicUser(UserDTO ud) {
		User u = em.find(User.class, ud.getId());
		if (u == null) {
			return false;
		} else {
			Usertype usertype = u.getUsertype();
			if (usertype.getId() == 4) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Method used to get all active office managers
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getActiveOfficeManagers() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		TypedQuery<User> q = em.createQuery(cq);

		List<User> users = q.getResultList();

		for (User u : users) {
			UserDTO ud = conv.fromEntityUser(u);
			if (isOfficeManager(ud) && u.getIsactive() == 1) {
				resultlist.add(conv.fromEntityUser(u));
			}
		}
		return resultlist;
	}

	/*
	 * added by sotocs
	 */
	@Override
	public List<UserDTO> getAllReplacedOfficeManagers() {
		List<UserDTO> resultlist = new ArrayList<>();
		UserDTO admin = getAdmin();

		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		TypedQuery<User> q = em.createQuery(cq);

		List<User> users = q.getResultList();

		for (User u : users) {
			User replacementUser = u.getUser();
			if (u.getIsactive() == 0 && replacementUser != null
					&& replacementUser.getId() != admin.getId()) {
				resultlist.add(conv.fromEntityUser(u));
			}
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by domain ascending
	 * 
	 * @return list of usersDto
	 */
	@Override
	public List<UserDTO> getUserOrderedByDomain() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		Join<User, Domain> owner = user.join(User_.domain);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.name))).orderBy(
				cb.asc(owner.get(Domain_.name)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {

			resultlist.add(conv.fromEntityUser(u));

		}
		return resultlist;

	}

	/**
	 * Method used to get all users ordered by domain descending
	 * 
	 * @return list of usersDto
	 */

	@Override
	public List<UserDTO> getUserOrderedByDomainDesc() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		Join<User, Domain> owner = user.join(User_.domain);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.name))).orderBy(
				cb.desc(owner.get(Domain_.name)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {

			resultlist.add(conv.fromEntityUser(u));

		}
		return resultlist;

	}

	/**
	 * Method used to get users ordered by username
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByUsername() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.username)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {

			resultlist.add(conv.fromEntityUser(u));

		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by username descending
	 * 
	 * @return list of usersDto
	 */
	@Override
	public List<UserDTO> getUserOrderedByUsernameDesc() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		cq.orderBy(cb.desc(user.get(User_.username)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {

			resultlist.add(conv.fromEntityUser(u));

		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by is active ascending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByIsActive() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.isactive)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by is active descending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByIsActiveDesc() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		cq.orderBy(cb.desc(user.get(User_.isactive)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by user type ascending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByUsertype() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		Join<User, Usertype> owner = user.join(User_.usertype);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.name))).orderBy(
				cb.asc(owner.get(Usertype_.name)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {

			resultlist.add(conv.fromEntityUser(u));

		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by user type descending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByUsertypeDesc() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		Join<User, Usertype> owner = user.join(User_.usertype);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.name))).orderBy(
				cb.desc(owner.get(Usertype_.name)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by name ascending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByName() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.name)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by name descending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByNameDesc() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		cq.orderBy(cb.desc(user.get(User_.name)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by email ascending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByEmail() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.email)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by email descending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByEmailDesc() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		cq.orderBy(cb.desc(user.get(User_.email)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by replaced by ascending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByReplacedby() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		Join<User, User> owner = user.join(User_.user);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.name))).orderBy(
				cb.asc(owner.get(User_.name)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by replaced by descending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUserOrderedByReplacedbyDesc() {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		Join<User, User> owner = user.join(User_.user);
		cq.select(user);
		cq.orderBy(cb.asc(user.get(User_.name))).orderBy(
				cb.desc(owner.get(User_.name)));
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			resultlist.add(conv.fromEntityUser(u));
		}
		return resultlist;
	}

	/**
	 * Method used to get all users ordered by user type and domain ascending
	 * 
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUsersByDomainandUsertype(int idDomain,
			int idUsertype) {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			Domain d = u.getDomain();
			Usertype type = u.getUsertype();
			if (d.getId() == idDomain && type.getId() == idUsertype) {
				resultlist.add(conv.fromEntityUser(u));
			}
		}
		return resultlist;
	}

	/**
	 * Method used to get all users by domain
	 * @return list of users
	 */
	@Override
	public List<UserDTO> getUsersByDomain(int idDomain) {
		List<UserDTO> resultlist = new ArrayList<>();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);
		
		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();
		
		for (User u : users) {
			Domain d =u.getDomain();
			if (d.getId() == idDomain) {
				resultlist.add(conv.fromEntityUser(u));
			}
		}
		return resultlist;
	}
	
	
	/**
	 * Method used set domain null
	 * 
	 * @param idDomain
	 */
	@Override
	public void setDomainNullByDomainId(int idDomain) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<User> cq = cb.createQuery(User.class);
		Root<User> user = cq.from(User.class);
		cq.select(user);

		TypedQuery<User> q = em.createQuery(cq);
		List<User> users = q.getResultList();

		for (User u : users) {
			Domain d = u.getDomain();
			if (d != null && d.getId() == idDomain) {
				if (em.find(User.class, u.getId()) != null) {
					u.setDomain(null);
					em.merge(u);
				}

			}
		}

	}
}
